#ifndef request_h
#define request_h

#include <WiFi.h>
#include <WebServer.h>
#include <LittleFS.h>
#include <ArduinoJson.h>
#include "StepMotor.h"
#include "motor.h"

String ssid;
String password;

WebServer server(80);

float injectAmount = 0;
float speed = 0;
float rpm = 0;
String selectedDrug = "";
StepMotor *movemotor = nullptr;
TaskHandle_t injectTaskHandle = NULL;
bool injectFinished = false;

struct DrugInfo
{
  String name;
  float total;
  float used;
  float remain;
  bool checked;
  float mmml;
};
DrugInfo drugs[3] = {
    {"1号", 0, 0, 0, false, 6.0},
    {"2号", 0, 0, 0, false, 6.0},
    {"3号", 0, 0, 0, false, 6.0}};

static float lastUsed[3] = {0, 0, 0}; // 记录每个药物上次used

void setMotorSpeedRPM(StepMotor &motor, double rpm, int steps_per_rev)
{
  double freq = rpm * steps_per_rev / 60.0;
  motor.motorSpeed(freq);
}

void handleRoot()
{
  if (LittleFS.exists("/index.html"))
  {
    File file = LittleFS.open("/index.html", "r");
    server.streamFile(file, "text/html");
    file.close();
  }
  else
  {
    server.send(404, "text/plain", "File not found");
  }
}

void handleWiFiConfig()
{
  if (LittleFS.exists("/wifi_config.html"))
  {
    File file = LittleFS.open("/wifi_config.html", "r");
    server.streamFile(file, "text/html");
    file.close();
  }
  else
  {
    server.send(404, "text/plain", "File not found");
  }
}

void handleSettings()
{
  if (LittleFS.exists("/settings.html"))
  {
    File file = LittleFS.open("/settings.html", "r");
    server.streamFile(file, "text/html");
    file.close();
  }
  else
  {
    server.send(404, "text/plain", "File not found");
  }
}
void handleConnectWiFi()
{
  if (server.hasArg("ssid") && server.hasArg("password"))
  {
    String newSSID = server.arg("ssid");
    String newPassword = server.arg("password");
    WiFi.begin(newSSID.c_str(), newPassword.c_str());
    unsigned long startAttemptTime = millis();
    while (WiFi.status() != WL_CONNECTED && millis() - startAttemptTime < 2000)
    {
      server.send(200, "text/plain", "正在连接到WiFi...");
    }
    File wifiFile = LittleFS.open("/wifi.txt", "w");
    wifiFile.println(newSSID);
    wifiFile.println(newPassword);
    wifiFile.close();
    ESP.restart();
  }
  else
  {
    server.send(400, "text/plain", "缺少SSID或密码");
  }
}

// 初始化位置，接收药物信息（名称、总量、复选框状态）
void handleInitPosition()
{
  if (server.hasArg("plain"))
  {
    StaticJsonDocument<512> doc;
    DeserializationError error = deserializeJson(doc, server.arg("plain"));
    if (error)
    {
      server.send(400, "text/plain", "JSON解析失败");
      return;
    }
    JsonArray arr = doc["drugs"].as<JsonArray>();
    int idx = 0;
    for (JsonObject obj : arr)
    {
      drugs[idx].name = obj["name"].as<String>();
      drugs[idx].total = obj["total"].as<float>();
      drugs[idx].checked = obj["checked"].as<bool>();

      // 如果该药物被选中，则根据差值设置电机方向和时间
      if (drugs[idx].checked)
      {
        float diff = drugs[idx].total - drugs[idx].remain;
        float time = 60 * abs(diff) * drugs[idx].mmml / 3000;
        int rpm_dir = (diff > 0) ? -3000 : 3000;

        if (idx == 0)
        {
          setMotorSpeedRPM(motor_0, rpm_dir, 200);
          vTaskDelay(time * 1000);
          setMotorSpeedRPM(motor_0, 0, 200);
        }
        else if (idx == 1)
        {
          setMotorSpeedRPM(motor_1, rpm_dir, 200);
          vTaskDelay(time * 1000);
          setMotorSpeedRPM(motor_1, 0, 200);
        }
        else if (idx == 2)
        {
          setMotorSpeedRPM(motor_2, rpm_dir, 200);
          vTaskDelay(time * 1000);
          setMotorSpeedRPM(motor_2, 0, 200);
        }
      }
      idx++;
      if (idx >= 3)
        break;
    }
    for (int i = 0; i < 3; i++)
    {
      drugs[i].used = 0;
    }
    server.send(200, "text/plain", "初始化位置成功");
  }
  else
  {
    server.send(400, "text/plain", "缺少参数");
  }
}

// 新增：返回mmml参数
void handleMmmlStatus()
{
  StaticJsonDocument<128> doc;
  JsonArray arr = doc.createNestedArray("mmml");
  for (int i = 0; i < 3; i++)
  {
    arr.add(drugs[i].mmml);
  }
  String result;
  serializeJson(doc, result);
  server.send(200, "application/json", result);
}

// 新增：更新mmml参数
void handleUpdateMmml()
{
  if (server.hasArg("plain"))
  {
    StaticJsonDocument<256> doc;
    DeserializationError error = deserializeJson(doc, server.arg("plain"));
    if (error)
    {
      server.send(400, "application/json", "{\"success\":false,\"msg\":\"JSON解析失败\"}");
      return;
    }
    JsonArray arr = doc["updates"].as<JsonArray>();
    for (JsonObject obj : arr)
    {
      int idx = obj["index"];
      float val = obj["mmml"];
      if (idx >= 0 && idx < 3 && val > 0)
      {
        drugs[idx].mmml = val;
      }
    }
    server.send(200, "application/json", "{\"success\":true}");
  }
  else
  {
    server.send(400, "application/json", "{\"success\":false,\"msg\":\"缺少参数\"}");
  }
}

void handleSetDrug()
{
  if (server.hasArg("name"))
  {
    selectedDrug = server.arg("name");
    bool found = false;
    for (int i = 0; i < 3; i++)
    {
      if (drugs[i].name == selectedDrug)
      {
        if (i == 0)
          movemotor = &motor_0;
        else if (i == 1)
          movemotor = &motor_1;
        else if (i == 2)
          movemotor = &motor_2;
        found = true;
        break;
      }
    }
    if (found)
    {
      server.send(200, "text/plain", "药物已选择: " + selectedDrug);
    }
    else
    {
      server.send(400, "text/plain", "未找到对应药物");
    }
  }
  else
  {
    server.send(400, "text/plain", "缺少药物名称参数");
  }
}

void handleSetSpeed()
{
  if (server.hasArg("value"))
  {
    speed = server.arg("value").toFloat();
    // int idx = server.hasArg("index") ? server.arg("index").toInt() : 0;
    // rpm = speed * drugs[idx].mmml * 60.0;
    server.send(200, "text/plain", "速度已设置为: " + String(speed));
  }
  else
  {
    server.send(400, "text/plain", "缺少速度参数");
  }
}

void handleSetAmount()
{
  if (server.hasArg("value"))
  {
    injectAmount = server.arg("value").toFloat();
    server.send(200, "text/plain", "注射量已设置为: " + String(injectAmount));
  }
  else
  {
    server.send(400, "text/plain", "缺少注射量参数");
  }
}

unsigned long injectStartTime = 0;
unsigned long injectedTime = 0;
// bool motorRunning = false;

void handleStart()
{
  if (movemotor == nullptr || speed <= 0 || injectAmount <= 0)
  {
    server.send(400, "text/plain", "参数错误");
    return;
  }
  int idx = 0;
  if (movemotor == &motor_0) idx = 0;
  else if (movemotor == &motor_1) idx = 1;
  else if (movemotor == &motor_2) idx = 2;
  float remain = drugs[idx].total - drugs[idx].used;
  if (remain <= 0.01)
  {
    server.send(400, "text/plain", "剩余量为0，无法注射");
    return;
  }
  lastUsed[idx] = drugs[idx].used;

  rpm = speed * drugs[idx].mmml * 60.0;
  motorRunning = true;
  injectStartTime = millis();
  injectedTime = 0;
  setMotorSpeedRPM(*movemotor, (double)rpm, 200);
  server.send(200, "text/plain", "注射已开始");
}

bool canResume = false; // 新增：是否允许继续注射

void handlePause()
{
  motorRunning = false;
  injectedTime += millis() - injectStartTime;
  if (movemotor != nullptr)
  {
    setMotorSpeedRPM(*movemotor, 0, 200);
  }
  canResume = true; // 允许继续注射
  server.send(200, "text/plain", "注射已暂停");
}

void handleResume()
{
  if (!canResume) // 新增：判断是否允许继续
  {
    server.send(400, "text/plain", "请先按暂停后再继续注射");
    return;
  }
  if (movemotor == nullptr || speed <= 0 || injectAmount <= 0)
  {
    server.send(400, "text/plain", "参数错误");
    return;
  }
  motorRunning = true;
  injectStartTime = millis();
  setMotorSpeedRPM(*movemotor, (double)rpm, 200);
  canResume = false; // 恢复后需再次暂停才能继续
  server.send(200, "text/plain", "注射已继续");
}

void handleInjectStatus()
{
  if (injectFinished)
  {
    server.send(200, "application/json", "{\"finished\":true}");
    injectFinished = false;
  }
  else
  {
    server.send(200, "application/json", "{\"finished\":false}");
  }
}

void handleDrugStatus()
{
  StaticJsonDocument<256> doc;
  JsonArray arr = doc.createNestedArray("remain");
  for (int i = 0; i < 3; i++)
  {
    float remain = drugs[i].total - drugs[i].used;
    drugs[i].remain = remain;
    if (remain < 0)
      remain = 0;
    arr.add(remain);
  }
  String result;
  serializeJson(doc, result);
  server.send(200, "application/json", result);
}

// 长按注射开始
void handleHoldStart()
{
  String drugName = server.arg("drug");
  float holdSpeed = server.arg("speed").toFloat();
  if (holdSpeed <= 0) {
    server.send(400, "text/plain", "速度参数错误");
    return;
  }
  // 选择药物
  bool found = false;
  int idx = 0;
  for (int i = 0; i < 3; i++) {
    if (drugs[i].name == drugName) {
      selectedDrug = drugName;
      if (i == 0) movemotor = &motor_0;
      else if (i == 1) movemotor = &motor_1;
      else if (i == 2) movemotor = &motor_2;
      drugs[i].checked = true;
      found = true;
      idx = i;
      break;
    }
  }
  if (!found) {
    server.send(400, "text/plain", "未找到对应药物");
    return;
  }
  // 判断剩余量
  float remain = drugs[idx].total - drugs[idx].used;
  if (remain <= 0.01) // 剩余量为0或负数
  {
    server.send(400, "text/plain", "剩余量为0，无法注射");
    return;
  }
  lastUsed[idx] = drugs[idx].used;
  speed = holdSpeed;
  injectAmount = 99999; // 极大值，保证只要松开就能停
  // 重新用当前mmml计算rpm
  rpm = speed * drugs[idx].mmml * 60.0;

  motorRunning = true;
  injectStartTime = millis();
  injectedTime = 0;
  setMotorSpeedRPM(*movemotor, (double)rpm, 200);
  server.send(200, "text/plain", "长按注射已开始");
}

// 长按注射停止
void handleHoldStop()
{
  motorRunning = false;
  injectedTime += millis() - injectStartTime;
  if (movemotor != nullptr) {
    setMotorSpeedRPM(*movemotor, 0, 200);
  }
  server.send(200, "text/plain", "长按注射已停止");
}

void request_setup()
{
  server.on("/", handleRoot);
  server.on("/wifi", handleWiFiConfig);
  server.on("/settings", handleSettings);
  server.on("/connect", handleConnectWiFi);
  server.on("/initPosition", handleInitPosition);
  server.on("/setDrug", handleSetDrug);
  server.on("/setSpeed", handleSetSpeed);
  server.on("/setAmount", handleSetAmount);
  server.on("/start", handleStart);
  server.on("/pause", handlePause);
  server.on("/resume", handleResume);
  server.on("/injectStatus", handleInjectStatus);
  server.on("/drugStatus", handleDrugStatus);
  server.on("/mmmlStatus", handleMmmlStatus);
  server.on("/updateMmml", HTTP_POST, handleUpdateMmml);
  // 新增长按注射接口
  server.on("/holdStart", handleHoldStart);
  server.on("/holdStop", handleHoldStop);

  server.begin();
}

void injectTask(void *pvParameters)
{
  for (;;)
  {
    if (motorRunning && movemotor != nullptr && speed > 0 && injectAmount > 0)
    {
      unsigned long now = millis();
      unsigned long totalTime = injectAmount / speed * 1000;
      if (now - injectStartTime + injectedTime >= totalTime)
      {
        setMotorSpeedRPM(*movemotor, 0, 200);
        motorRunning = false;
        injectedTime = 0;
        injectFinished = true;
      }
    }
    vTaskDelay(20 / portTICK_PERIOD_MS);
  }
}

void drugRemainTask(void *pvParameters)
{
  for (;;)
  {
    if (motorRunning && movemotor != nullptr && speed > 0 && injectAmount > 0)
    {
      int idx = -1;
      for (int i = 0; i < 3; i++)
      {
        if (drugs[i].checked && movemotor == ((i == 0) ? &motor_0 : (i == 1) ? &motor_1 : &motor_2))
        {
          idx = i;
          break;
        }
      }
      if (idx != -1)
      {
        unsigned long now = millis();
        float elapsed = (now - injectStartTime + injectedTime) / 1000.0f;
        float curUsed = lastUsed[idx] + speed * elapsed;
        float maxUsed = lastUsed[idx] + injectAmount;
        if (curUsed > maxUsed)
          curUsed = maxUsed;
        if (curUsed > drugs[idx].total)
          curUsed = drugs[idx].total;
        drugs[idx].used = curUsed;
      }
    }
    else
    {
      for (int i = 0; i < 3; i++)
      {
        lastUsed[i] = drugs[i].used;
      }
    }
    // 实时更新剩余量
    for (int i = 0; i < 3; i++)
    {
      drugs[i].remain = drugs[i].total - drugs[i].used;
      if (drugs[i].remain < 0) drugs[i].remain = 0;
    }
    vTaskDelay(20 / portTICK_PERIOD_MS);
  }
}

#endif